package cn.net.shuxing.yifu.common.front.controller;


import cn.net.shuxing.yifu.common.bean.User;
import cn.net.shuxing.yifu.common.bean.UserInfoBind;
import cn.net.shuxing.yifu.common.bean.UserRole;
import cn.net.shuxing.yifu.common.constant.RegistType;
import cn.net.shuxing.yifu.common.constant.UserState;
import cn.net.shuxing.yifu.common.constant.UserType;
import cn.net.shuxing.yifu.common.dto.BaseDto;
import cn.net.shuxing.yifu.common.constant.CodeConst;
import cn.net.shuxing.yifu.common.service.*;
import cn.net.shuxing.yifu.common.util.*;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.Map;


@Api("公共模块控制器")
@RestController
@RequestMapping("/front/public")
public class PublicController {

    @Autowired
    private UserService userService;

    @Autowired
    private SmsUserService smsUserService;

    @Autowired
    private MailService mailService;

    @Autowired
    private JedisUtil jedisUtil;

    @Autowired
    private OssCommonService ossCommonService;

    @Autowired
    private UserPasswordService userPasswordService;

    @Autowired
    private MarkImageService markImageService;

    @Autowired
    private UserInfoBindService userInfoBindService;

    @Autowired
    private UserRoleService userRoleService;

//    @RequestMapping("/sendSMS")
//    public BaseDto sendSMS(String phoneNum){
//        BaseDto baseDto = new BaseDto();
//        smsUserService.sendSMS(phoneNum);
//        return baseDto;
//    }

    /**
     * 检验用户名是否存在
     *
     * @param username
     * @return
     */
    public BaseDto checkUsername(String username) {
        BaseDto baseDto = new BaseDto();
//        User user = userService.checkUser(username);
        UserInfoBind userInfoBind = userInfoBindService.checkUser(username);
        if (userInfoBind == null) {
            baseDto.setCode(CodeConst.ERROR);
            baseDto.setMsg("用户不存在!");
        } else {
            baseDto.setCode(CodeConst.OK);
            baseDto.setData("ok");
        }
        return baseDto;
    }

    /**
     * 判断UserInfoBind中是否包含手机号
     *
     * @param username
     * @return
     */
    public BaseDto checkUsernameUseable(String username) {
        BaseDto baseDto = new BaseDto();
        UserInfoBind userInfoBind = userInfoBindService.checkUser(username);
        if (userInfoBind != null) {
            if (!userRoleService.getByUserIdAndUserRoles(userInfoBind.getId(), UserType.MEMBER, UserType.NONE)) {
                baseDto.setCode(CodeConst.ERROR);
                baseDto.setMsg("用户名已存在!");
            } else {
                baseDto.setCode(CodeConst.OK);
                baseDto.setData("用户名可以使用");
            }
        } else {
            baseDto.setCode(CodeConst.OK);
            baseDto.setData("用户名可以使用");
        }
        return baseDto;
    }

    @ApiOperation(value = "发送登录验证码", httpMethod = "POST")
    @ApiImplicitParam(name = "username", value = "用户名", required = true, dataType = "String", paramType = "query")
    @RequestMapping("/login/verifyCode/send")
    public BaseDto sendLoginVerifyCode(String username) {
        boolean contains = username.contains("@");
        UserInfoBind userInfoBind = userInfoBindService.checkUser(username);
        if (userInfoBind == null) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(CodeConst.ERROR);
            baseDto.setMsg("该用户不存在");
        }
        BaseDto baseDto = null;
        if (!contains) {
            baseDto = smsUserService.sendSMS(username, RedisKeyCreator.loginVerifyCode(username));
        } else {
            baseDto = mailService.sendMail(username, RedisKeyCreator.loginVerifyCode(username));
        }

        return baseDto;
    }

    @ApiOperation(value = "发送注册验证码", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "registType", value = "注册类型,0为手机号,1为邮箱", required = true, dataType = "Integer", paramType = "query")
    })
    @RequestMapping("/regist/verifyCode/send")
    public BaseDto sendRegistVerifyCode(String username, Integer registType) {
        BaseDto baseDto1 = checkUsernameUseable(username);
//        如果该手机号已经出现会员身份
        if (baseDto1.getCode() == CodeConst.ERROR) {
            return baseDto1;
        }
        BaseDto baseDto;
        if (registType == RegistType.PHONE) {
            baseDto = smsUserService.sendSMS(username, RedisKeyCreator.registPasswordVerifyCodeKey(username));
        } else if (registType == RegistType.MAIL) {
            baseDto = mailService.sendMail(username, RedisKeyCreator.registPasswordVerifyCodeKey(username));
        } else {
            baseDto = new BaseDto();
            baseDto.setCode(CodeConst.ERROR);
            baseDto.setMsg("注册类型错误，注册类型只能为0(手机号注册)，1(邮箱注册)");
            return baseDto;
        }
        if (baseDto.getCode() == CodeConst.OK)
            baseDto.setData("success");
        return baseDto;
    }

    @RequestMapping("/agree")
    public BaseDto agreeProtocal(Integer userId) {
        User user = userService.getByPrimaryKeyWithoutComplete(userId);
        if (user == null)
            return BaseDto.error("此用户不存在");
        user.setHasAgree(1);
        userService.update(user);
        return BaseDto.ok("success");
    }

    /**
     * 登录
     *
     * @param username
     * @param code
     * @return
     */
    @ApiOperation(value = "登录", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "code", value = "验证码", required = true, dataType = "String", paramType = "query")
    })
    @RequestMapping("/login")
    public BaseDto login(String username, String code) {
        BaseDto baseDto1 = checkUsername(username);
        if (baseDto1.getCode() == CodeConst.ERROR)
            return baseDto1;
        UserInfoBind userInfoBind = userInfoBindService.checkUser(username);
        User user1 = userService.getByPrimaryKey(userInfoBind.getId());
        BaseDto baseDto = new BaseDto();
//        String verifyCode = jedisUtil.getJedis().get("username:" + phoneNum + ":verifyCode");
        //Jedis //jedis = jedisUtil.getJedis();
        String loginProcessStr = jedisUtil.get(RedisKeyCreator.loginProcess(userInfoBind.getId()));

        if (!StringUtils.hasText(loginProcessStr) || !loginProcessStr.equals("2")) {
            //jedisUtil.close();
            return BaseDto.error("请先完成拼图验证登录");
        }


        String verifyCode = jedisUtil.get(RedisKeyCreator.loginVerifyCode(username));

        //username:15088728513:verifyCode
        if (!code.equals(verifyCode)) {
            baseDto.setCode(CodeConst.ERROR);
            baseDto.setMsg("验证码错误");
            long ttl = jedisUtil.ttl(RedisKeyCreator.loginVerifyCode(username));
            ttl -= 60 * 5;
            if (ttl < 0) {
                jedisUtil.del(RedisKeyCreator.loginVerifyCode(username));
            }
            jedisUtil.expire(RedisKeyCreator.loginVerifyCode(username), (int) ttl);
            //jedisUtil.close();
        } else {
            String phoneNum = userInfoBind.getPhoneNum();
            String sPhoneNum = userInfoBind.getSPhoneNum();
            String mail = userInfoBind.getMail();
            if (username == phoneNum)
                user1.setUsername(username);
            if (username.equals(sPhoneNum))
                user1.setUsername(username);
            if (username.equals(mail))
                user1.setUsername(mail);
            userService.update(user1);
            User user = user1;
            User userlogin = user;
            Integer id = userlogin.getId();
            jedisUtil.del(RedisKeyCreator.loginProcess(user.getId()));
            jedisUtil.set(RedisKeyCreator.login(id),JSON.toJSONString(userlogin));
            jedisUtil.expire(RedisKeyCreator.login(id),7 * 24 * 3600);
//            jedisUtil.setex(RedisKeyCreator.login(id), 7 * 24 * 3600, JSON.toJSONString(userlogin));
            //jedisUtil.close();
            baseDto.setData(userlogin);
        }
        return baseDto;
    }

    /**
     * 注册
     *
     * @param username
     * @param password
     * @param verifyCode
     * @return
     */
    @ApiOperation(value = "注册")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "verifyCode", value = "验证码", required = true, dataType = "String", paramType = "query")
    })
    @RequestMapping("/register")
    public BaseDto register(String username, String password, Integer registType, String verifyCode,
                            @RequestParam(defaultValue = "0", value = "language") int language) {
        BaseDto baseDto = new BaseDto();
        String code = jedisUtil.get(RedisKeyCreator.registPasswordVerifyCodeKey(username));
//      判断手机号或者邮箱是否可用
        BaseDto baseDto1 = checkUsernameUseable(username);
//      如果该手机号已经出现会员身份
        if (baseDto1.getCode() == CodeConst.ERROR) {
            return BaseDto.error("此账号已被注册");
        } else {
            if (!verifyCode.equals(code)) {
                baseDto.setCode(CodeConst.ERROR);
                baseDto.setMsg("验证码错误!");
            } else {
//                进行完全无身份和有股东身份两种情况的处理
                UserInfoBind userInfoBind = userInfoBindService.checkUser(username);
                if (userInfoBind == null) {
                    User user = new User();
                    user.setUsername(username);
                    user.setPassword(password);
                    user.setRegistType(registType);
                    user.setLanguage(language);
                    int userId = userService.regist(user);
                    if (userId < 1)
                        return BaseDto.error("此用户名已被绑定");
                    User byPrimaryKey = userService.getByPrimaryKey(userId);
                    baseDto.setData(byPrimaryKey);
                } else {
                    UserRole userRole = userRoleService.getByUserIdAndUserRole(userInfoBind.getId(), UserType.SHAREHOLDER);
//                    是完全无身份
                    if (userRole == null) {
                        User user = new User();
                        user.setUsername(username);
                        user.setPassword(MD5Util.md5(password));
                        user.setRegistType(registType);
                        user.setLanguage(language);
                        int userId = userService.regist(user);
                        if (userId < 1)
                            return BaseDto.error("此用户名已被绑定");
                        User byPrimaryKey = userService.getByPrimaryKey(userId);
                        baseDto.setData(byPrimaryKey);
                    } else {
//                    只有股东身份
                        User user = userService.getByPrimaryKey(userRole.getUserId());
                        user.setPassword(MD5Util.md5(password));
                        user.setLanguage(language);
                        userService.update(user);
                        int roleId = userRoleService.insert(user.getId(), UserType.NONE, UserState.ACTIVATING);
                        if (roleId < 1) {
                            return BaseDto.error("插入角色失败");
                        } else {
                            baseDto.setData(user);
                        }
                    }
                }
            }
            return baseDto;
        }
    }

    @ApiOperation(value = "发送找回密码验证码", httpMethod = "POST")
    @ApiImplicitParam(name = "username", value = "用户名", required = true, dataType = "String", paramType = "query")
    @RequestMapping("/password/find/verifyCode/send")
    public BaseDto sendFindPasswordVerifyCode(String username) {
        User user = userService.searchByUsername(username);
        if (user == null) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(CodeConst.ERROR);
            baseDto.setMsg("该用户不存在");
        }
        Integer registType = user.getRegistType();
        BaseDto baseDto = null;
        if (registType == RegistType.PHONE) {
            baseDto = smsUserService.sendSMS(username, RedisKeyCreator.findPasswordVerifyCodeKey(username));
        } else if (registType == RegistType.MAIL) {
            baseDto = mailService.sendMail(username, RedisKeyCreator.findPasswordVerifyCodeKey(username));
        }

        return baseDto;
    }

    /**
     * 找回密码
     *
     * @param username
     * @param code
     * @param password
     * @return
     */
    @ApiOperation(value = "找回密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "password", value = "新密码", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "verifyCode", value = "验证码", required = true, dataType = "String", paramType = "query")
    })
    @RequestMapping("/findSecret")
    public BaseDto findSecret(String username, String code, String password) {
        BaseDto baseDto = new BaseDto();
        BaseDto baseDtoCheck = checkUsername(username);
        if (baseDtoCheck.getCode() == CodeConst.ERROR) {
            return baseDtoCheck;
        } else {
            //Jedis //jedis = jedisUtil.getJedis();
            String verifyCode = jedisUtil.get(RedisKeyCreator.findPasswordVerifyCodeKey(username));
            //jedisUtil.close();
            if (!verifyCode.equals(code)) {
                baseDto.setCode(CodeConst.ERROR);
                baseDto.setMsg("验证码错误");
            } else {
                baseDto.setData(userService.update(username, password));
            }
            return baseDto;
        }
    }

    /**
     * 退出登录
     *
     * @param userId
     * @return
     */
    @ApiOperation(value = "退出登录", httpMethod = "DELETE")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", required = true, dataType = "Integer", paramType = "query")
    })
    @RequestMapping("/exitLogin")
    public BaseDto exitLogin(int userId) {
        BaseDto baseDto = new BaseDto();
        //Jedis //jedis = jedisUtil.getJedis();
        jedisUtil.del(RedisKeyCreator.login(userId));
        //jedisUtil.close();
        baseDto.setData("退出登录完成");
        return baseDto;
    }

    /**
     * 获取拼图
     *
     * @param userId 用户id
     * @return 结构如下
     * {
     * "code": 0,
     * "msg": "",
     * "data": {
     * "originImageUrl": "背景图的url",
     * "sliderImageUrl": "滑块图的url",
     * "index": "这张图的唯一标识"
     * }
     * }
     */
    @RequestMapping("/user/markImage")
    public BaseDto generateMarkImg(Integer userId) {
        User user = userService.getByPrimaryKey(userId);
        if (user == null) {
            BaseDto baseDto = BaseDto.error("该用户不存在");
            return baseDto;
        }

        Map<String, String> map = markImageService.generateMarkImage(userId);
        return BaseDto.ok(map);
    }

    /**
     * 验证拼图
     *
     * @param userId 用户id
     * @param point  滑块最左端x坐标
     * @param index  原型图唯一标识,调用/front/public/user/markImage接口时会传过去
     * @return
     */
    @RequestMapping("/user/markImage/verify")
    public BaseDto verifyMarkImg(Integer userId, Integer point, Integer index) {
        if (index == null) {
            return BaseDto.error("图片唯一标识不能为空");
        }
        //Jedis //jedis = jedisUtil.getJedis();
        String loginProcessStr = jedisUtil.get(RedisKeyCreator.loginProcess(userId));
        if (!StringUtils.hasText(loginProcessStr) || !loginProcessStr.equals("1")) {
            //jedisUtil.close();
            return BaseDto.error("请先完成用户名密码登录");
        }
        String userMarkImagePoint = jedisUtil.get(RedisKeyCreator.sliderImagePosition(index));
        if (!StringUtils.hasText(userMarkImagePoint)) {
            //jedisUtil.close();
            return BaseDto.error("错误次数太多或此拼图已过期,请重新调用 获取拼图接口(/front/public/user/markImage?userId=" + userId + ")");
        }

        if (markImageService.verifyPosition(point, index)) {
            jedisUtil.incr(RedisKeyCreator.loginProcess(userId));
            //jedisUtil.close();

            return BaseDto.ok("success");
        } else {
            long ttl = jedisUtil.ttl(RedisKeyCreator.userMarkImagePoint(userId));
            ttl -= 60;
            if (ttl <= 0) {
                jedisUtil.del(RedisKeyCreator.userMarkImagePoint(userId));
            } else {
                jedisUtil.expire(RedisKeyCreator.userMarkImagePoint(userId), (int) ttl);
            }
            //jedisUtil.close();
            return BaseDto.error("拼图位置不正确,请重试");
        }
    }

    @ApiOperation(value = "使用用户名和密码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String", paramType = "query")
    })
    @RequestMapping("/login/password")
    public BaseDto loginWithPassword(String username, String password) {
        UserInfoBind userInfoBind = userInfoBindService.checkUser(username);
        if (userInfoBind == null) {
            BaseDto baseDto = BaseDto.error("该用户名不存在");
            return baseDto;
        } else {
            User user = userService.getByPrimaryKey(userInfoBind.getId());
            if (user == null) {
                BaseDto baseDto = BaseDto.error("该用户名不存在");
                return baseDto;
            }
            if (!user.getPassword().equals(MD5Util.md5(password))) {
                BaseDto baseDto = BaseDto.error("密码输入错误");
                return baseDto;
            }
            BaseDto baseDto = new BaseDto();
            baseDto.setData(user);
            //Jedis //jedis = jedisUtil.getJedis();
            jedisUtil.set(RedisKeyCreator.loginProcess(user.getId()), "1");
            //jedisUtil.close();
            return baseDto;
        }
    }

    /**
     * 获取用户当前使用语言
     *
     * @param userId
     * @return
     */
    @RequestMapping("/language/get")
    public BaseDto userLanguage(Integer userId) {
        BaseDto baseDto = new BaseDto();
        BigDecimal language = new BigDecimal(0);
        String s = jedisUtil.get(RedisKeyCreator.userLanguage(userId));
        if (!StringUtils.hasText(s)) {
            Integer userReal = userService.getByPrimaryKey(userId).getLanguage();
            language = new BigDecimal(userReal);
        } else {
            language = new BigDecimal(s);
        }
        baseDto.setData(language);
        return baseDto;
    }


    @RequestMapping("/language/set")
    public BaseDto setLanguage(Integer userId) {
        BaseDto baseDto = new BaseDto();
        User user = userService.getByPrimaryKey(userId);
        Integer language = user.getLanguage();
        Integer newLan = 0;
        if (language==0){
            newLan = 1;
        }
        user.setLanguage(newLan);
        userService.update(user);
        jedisUtil.set(RedisKeyCreator.userLanguage(userId), newLan.toString());
        baseDto.setCode(0);
        if (newLan == 0){
            baseDto.setData("切换成功");
        }
        if (newLan == 1){
            baseDto.setData("Change Success!");
        }
        return baseDto;
    }
}